﻿using System;
using System.IO;
using System.Collections.Generic;
using RFServer.ServiceWCF;
using RFServer.Functions;

namespace RFServer.Drive
{
    public class TagList
    {
        private List<string> tags;

        /// <summary>
        /// Количество тэгов в классе
        /// </summary>

        public int Count { get { return tags.Count; } private set { } }

        /// <summary>
        /// Конструкор
        /// </summary>
        /// <param name="slashedTags">Набор тэгов</param>

        public TagList(List<string> tags)
        {
            this.tags = new List<string>();

            foreach (string tag in tags)
                this.tags.Add(tag);

        }

        /// <summary>
        /// Конвертация списка тэго в массив
        /// </summary>
        /// <returns>Массив тэгов</returns>

        public string[] ToArray()
        {
            return tags.ToArray();
        }
        
        /// <summary>
        /// Индексатор
        /// </summary>
        /// <param name="i">Индекс тэга</param>
        /// <returns>Тэг с индексом i</returns>

        public string this[int i]
        {
            get
            {
                if (i < Count)
                    return tags[i];
                else 
                    throw new IndexOutOfRangeException("Invalid tag index");
            }

            set
            {
                
            }
        }
    }

    public class FileLink
    {
        public string Path { get; private set; }            // Полный путь к файлу (r:\тэг1\тэг2\файл.txt)
        public string FileName { get; private set; }        // Имя файла (файл.txt)
        public TagList Tags { get; private set; }           // Массив тэгов (тэг1, тэг2)
        public string RealFileName { get; private set; }    // Физическое размещение файла на диске пользователя
                                                            // (если реальный файл не найден, то свойство имеет
                                                            // значение null)
        /// <summary>
        /// Конструтор. Разбивает полный путь к файлу в RFS на
        /// имя файла и его тэги. Осуществляет поиск реального
        /// месторасположения файла на диске пользователя
        /// </summary>
        /// <param name="path">
        /// Путь в RFS (R:\игры\стратегии\aoe2.exe)
        /// </param>

        public FileLink(string path)
        {
            Path = path;

            // Извлекаем имя файла

            FileName = Path.GetFileName();

            // Извлекаем тэги

            List<string> tags = new List<string>(Path.Split('\\'));

            tags.RemoveAt(0);
            tags.RemoveAt(tags.Count - 1);

            Tags = new TagList(tags);

            // Получаем реальный файл на диске

            SetRealFileName();
        }

        /// <summary>
        /// Функция устанавливает правильное значение свойства
        /// RealFileName
        /// </summary>

        private void SetRealFileName()
        {
            int i = 0;

            try
            {
                /* Соединяемся по NamedPipe с сервером */

                ILocalService service = LocalService.Connect();

                if (service == null)
                    throw new Exception("Failed to create NamedPipe channel");

                /* Делаем SELECT-запрос и получаем ответ в виде списка файлов */
                /* file1?type1|file2|type2|...                                */

                string[] files = service.Select(Tags.ToArray());

                // В полученном списке ищем файл, имя которого совпадает
                // с FileName

                for (i = 0; i < files.Length; i++)
                {
                    string filePathName = files[i].Split('?')[0];
                    string fileName = filePathName.GetFileName();

                    // Нет чувствительности к регистру

                    if (fileName.ToUpper() == FileName.ToUpper())
                    {
                        RealFileName = filePathName;
                        break;
                    }
                }

                // Если после проверки всех файлов с указанными тэгами
                // не было ни одного с именем FileName, значит и реального
                // файла на диске с такими тэгами не существует

                if (i == files.Length)
                {
                    RealFileName = null;
                    return ;
                }

                // Если файл не существует на диске, значит свойство
                // RealFileName бесполезно

                if (!File.Exists(RealFileName))
                {
                    RealFileName = null;
                    return ;
                }

                /* Отсоединение от сервера NamedPipe */

                LocalService.Disconnect(service);
            }
            catch (Exception e)
            {
                Setup.Log("[database]: Error getting real file name for " + Path, e);
                RealFileName = null;
            }
        }
    }
}
